package demo.javax.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * <h1>过滤器：</h1>依赖于servlet容器。在实现上基于函数回调，可以对几乎所有请求进行过滤，但是缺点是一个过滤器实例只能在容器初始化时调用一次。
 * 使用过滤器的目的是用来做一些过滤操作，获取我们想要获取的数据，比如：在过滤器中修改字符编码；在过滤器中修改HttpServletRequest的一些参数，包括：过滤低俗文字、危险字符等。
 * <b>过滤器的运行是依赖于servlet容器的，跟springmvc等框架并没有关系。并且，多个过滤器的执行顺序跟xml文件中定义的先后关系有关</b>
 * <p>
 * Filter可以认为是Servlet的一种“加强版”，它主要用于对用户请求进行预处理，也可以对HttpServletResponse进行后处理，是个典型的处理链。
 * Filter也可以对用户请求生成响应，这一点与Servlet相同，但实际上很少会使用Filter向用户请求生成响应。使用Filter完整的流程是：
 * Filter对用户请求进行预处理，接着将请求交给Servlet进行预处理并生成响应，最后Filter再对服务器响应进行后处理。
 * <p>
 * Filter有如下几个用处。
 * <li>在HttpServletRequest到达Servlet之前，拦截客户的HttpServletRequest。
 * <li>根据需要检查HttpServletRequest，也可以修改HttpServletRequest头和数据。
 * <li>在HttpServletResponse到达客户端之前，拦截HttpServletResponse。
 * <li>根据需要检查HttpServletResponse，也可以修改HttpServletResponse头和数据。
 * <p>
 * 
 * Filter有如下几个种类。
 * <li>用户授权的Filter：Filter负责检查用户请求，根据请求过滤用户非法请求。
 * <li>日志Filter：详细记录某些特殊的用户请求。
 * <li>负责解码的Filter:包括对非标准编码的请求解码。
 * <li>能改变XML内容的XSLT Filter等。
 * <li>Filter可以负责拦截多个请求或响应；一个请求或响应也可以被多个Filter拦截。
 * 
 * <p>
 * 创建一个Filter只需两个步骤
 * <li>创建Filter处理类
 * <li>web.xml文件中配置Filter
 * <p>
 * 
 * <pre>
 * <!-- 自定义过滤器：testFilter1 -->   
   <filter>  
        <filter-name>testFilter1</filter-name>  
        <filter-class>cn.zifangsky.filter.TestFilter1</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>testFilter1</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>
 * </pre>
 *
 * <h1>拦截器（Interceptor）和过滤器（Filter）的一些用途</h1>
 * <li>Authentication Filters
 * <li>Logging and Auditing Filters
 * <li>Image conversion Filters
 * <li>Data compression Filters
 * <li>Encryption Filters
 * <li>Tokenizing Filters
 * <li>Filters that trigger resource access events
 * <li>XSL/T filters
 * <li>Mime-type chain Filter
 * 
 * <h2>Request Filters 可以:</h2>
 * <li>执行安全检查 perform security checks
 * <li>格式化请求头和主体 reformat request headers or bodies
 * <li>审查或者记录日志 audit or log requests
 * <li>根据请求内容授权或者限制用户访问 Authentication-Blocking requests based on user identity.
 * <li>根据请求频率限制用户访问
 * 
 * <h2>Response Filters 可以:</h2>
 * <li>压缩响应内容,比如让下载的内容更小 Compress the response stream
 * <li>追加或者修改响应 append or alter the response stream
 * <li>创建或者整体修改响应 create a different response altogether
 * <li>根据地方不同修改响应内容 Localization-Targeting the request and response to a particular locale.
 */
public class FilterDemo implements Filter {

    private FilterConfig filterConfig;

    public FilterConfig getFilterConfig() {
        System.err.println("...getFilterConfig...");
        return filterConfig;
    }

    public void setFilterConfig(FilterConfig filterConfig) {
        System.err.println("...setFilterConfig...");
        this.filterConfig = filterConfig;
    }

    /**
     * 当容器销毁 Filter 实例时调用该方法，可以在方法中销毁资源，该方法在 Filter 的生命周期只会被调用一次。
     */
    @Override
    public void destroy() {
        System.err.println("...filter destroy...");
    }

    /**
     * Web 容器每一次请求都会调用该方法。该方法将容器的请求和响应作为参数传递进来， FilterChain 用来调用下一个 Filter。
     * 实现过滤功能，该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request)，也可实现对服务器响应进行后处理(ServletResponse
     * response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前，即对用户请求进行预处理；执行该方法之后，即对服务器响应进行后处理。
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.err.println("...doFilter...");
        chain.doFilter(request, response);// 看到这没，这只要是传递下一个Filter
    }

    /**
     * 当容器初始化 Filter 时调用，该方法在 Filter 的生命周期只会被调用一次，一般在该方法中初始化一些资源，FilterConfig 是容器提供给 Filter 的初始化参数， 在该方法中可以抛出
     * ServletException 。init 方法必须执行成功，否则 Filter 可能不起作用，出现以下两种情况时，web 容器中 Filter 可能无效： 1）抛出 ServletException 2）超过 web
     * 容器定义的执行时间。
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.err.println("...init Filter...");
        this.filterConfig = filterConfig;
    }

}
